// import com.alibaba.druid.sql.ast.SQLExpr;
// import com.alibaba.druid.sql.ast.SQLExprImpl;
// import com.alibaba.druid.sql.ast.SQLReplaceable;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;

// import java.util.ArrayList;
// import java.util.List;

#include "SQLGroupingSetExpr.h"
#include "../../visitor/SQLASTVisitor.h"
#include "../../../utils/listTran.h"
#include "../../../utils/instanceof.h"
#include "../../../utils/ifeq.h"

SQLGroupingSetExpr::SQLGroupingSetExpr()
{
  parameters = SQLExpr_list_ptr();
}
SQLObject_ptr SQLGroupingSetExpr::clone()
{
  SQLObject_ptr clone_tmp = std::shared_ptr<SQLGroupingSetExpr>(new SQLGroupingSetExpr());
  std::shared_ptr<SQLGroupingSetExpr> x = std::dynamic_pointer_cast<SQLGroupingSetExpr>(clone_tmp);
  // SQLGroupingSetExpr x = new SQLGroupingSetExpr();
  for (SQLExpr_ptr p : *parameters)
  {
    SQLExpr_ptr p2 = std::dynamic_pointer_cast<SQLExpr>(p->clone());
    p2->setParent(x);
    x->parameters->push_back(p2);
  }
  return x;
}

SQLExpr_list_ptr SQLGroupingSetExpr::getParameters()
{
  return parameters;
}

void SQLGroupingSetExpr::addParameter(SQLExpr_ptr parameter)
{
  if (parameter != nullptr)
  {
    parameter->setParent(SharedObject(SQLGroupingSetExpr));
  }
  this->parameters->push_back(parameter);
}

//@Override
void SQLGroupingSetExpr::accept0(SQLASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(SQLGroupingSetExpr)))
  {
    SQLObject_list_ptr tmp = ListTran::tran_class<SQLExpr, SQLObject>(parameters);
    acceptChild(visitor, tmp);
  }
  visitor->endVisit(SharedObject(SQLGroupingSetExpr));
}

//@Override
SQLObject_list_ptr SQLGroupingSetExpr::getChildren()
{
  SQLObject_list_ptr newClass = SQLObject_list_ptr();
  for (auto it : *this->parameters)
  {
    newClass->push_back(std::dynamic_pointer_cast<SQLObject>(it));
  }
  return newClass;
  // return this->parameters;
}

//@Override
int SQLGroupingSetExpr::hashCode()
{
  int prime = 31;
  int result = 1;
  // result = prime * result + parameters.hashCode();
  result = prime * result + parameters->size();
  return result;
}

//@Override
bool SQLGroupingSetExpr::equals(Object_ptr obj)
{
  if (this == obj.get())
  {
    return true;
  }
  if (obj == nullptr)
  {
    return false;
  }
  if (!(instanceof <Object, SQLGroupingSetExpr>(obj.get())))
  {
    return false;
  }
  std::shared_ptr<SQLGroupingSetExpr> other = std::dynamic_pointer_cast<SQLGroupingSetExpr>(obj);
  if (!IFEQ::ifeq(parameters, other->parameters))
  {
    return false;
  }
  return true;
}

//@Override
BOOL_ptr SQLGroupingSetExpr::replace(SQLExpr_ptr expr, SQLExpr_ptr target)
{
  auto it_parameters = parameters->begin();
  for (int i = 0; i < parameters->size(); i++)
  {
    std::advance(it_parameters, i);
    if ((*it_parameters) == expr)
    {
      target->setParent(SharedObject(SQLGroupingSetExpr));
      (*it_parameters) = target;
      return BOOL::TRUE;
    }
  }
  return BOOL::FALSE;
}
